#ifndef FLEXICAL_H
#define FLEXICAL_H
#include "ffile.hpp"
#include <iostream>
#include <vector>
#include <set>

#define WORDS_NUM 50
#define STRING_MAX_NUM 1000

//允许一个标准规格的码可以存在的最大长度
#define SINGLE_WORDS_NUM 30
/*
 *  单个读取字符允许最大长度
 *  这个考虑到很长的表达式没有加空格的因素，所以将这个值暂定为100
 *  如需考虑优化，再说
 */
#define WORD_MAX_SIZE 100

/*
 *词法分析：
 *种别码：  
 *  标识符  1
 *  常量    2
 *  运算符  3
 *  分隔符  4
 *  保留字  5              
 * 
 *  这里规定： 
 *      1) 以下划线或字母开头定义为标识符（函数名或变量名）
 *      2) 以数字开头定义为数字常量 
 *      3) 暂时规定分隔符只能单个出现，多个分隔符不构成运算符结构
 *      硬性规定--->这里考虑到shell脚本的语法规则 eg:[[]],不将有两个分隔符组成的符号解释为除分隔符以外的符号
 *  
 *  一些特殊的值得注意的：
 *      ,是逗号运算符，而不是分割符,这个运算符返回的值时逗号右边的值    [源自C规范]
 *      =是赋值运算符,这个运算表达式返回的值时等号左边的值            [源自C规范] 
 * 
 */          
namespace fairy{
class FLexical
{
    typedef std::vector< std::pair<std::string, int> > LD;
public:
    FLexical(const char *);
    auto analysis() -> int; 

    //判断一个串是不是保留字
    inline auto is_word(const char *str) -> bool { return words.count(str) ? true : false; };
    //判断一个串是不是运算符
    inline auto is_count(const char *str) -> bool {
        return (count_relation.count(str) || 
            count_arithmetic.count(str) || 
            count_logic.count(str)) ? true : false;
        };
    //判断一个字符是不是组成运算符的元素
    inline auto is_alone_count(const char &chr) -> bool {return count_words.count(chr) ? true : false;}
    //判断一个字符是不是分割符
    inline auto is_border(const char &chr) -> bool {return border.count(chr) ? true : false;}
    //输出词法分析表
    auto display_data() -> void;

private:
    //脚本文件操作符
    Ffile fairy;
    //词法分析后，所有的词数据将保存在这个容器之中，供语法分析和调试使用
    LD lexicaldata;
    //单词读取字符串
    char word[WORD_MAX_SIZE] = {0};      
    
    //保留字集合
    std::set<std::string> words{"for", "while", "if", "else", "return", "continec", "break",
        "static", "continue", "class", "public", "private"};
    //分隔符集合
    std::set<char> border{'(', ')', '{', '}', ';'};
    //所有的算数运算符的组成元素
    std::set<char> count_words{'+', '-', '*', '/', '%', '>', '<', '=', '|', '!', '&', ','};
     /* 
      * 算数运算符集合
      * 这里我将“，”和“=”分类到算数运算符中，影响不大，他们的结果都是返回一个运算表达式的值
      */
    std::set<std::string> count_arithmetic{"+", "-", "*", "/", "%", "++", "=", ",", "--"};
    //关系运算符集合
    std::set<std::string> count_relation{">", "<", "==", "!=", ">=", "<="};
    //逻辑运算符集合
    std::set<std::string> count_logic{"&&", "||", "!"};
    //这里应该有一个二进制运算符，先算了
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
};
}

#endif